package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.BaseEntity;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliyunIotProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceDataVo;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.retreat.DeviceVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    Client client;

    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @Autowired
    AliyunIotProperties aliyunIotProperties;

    @Autowired
    DeviceMapper deviceMapper;
    @Override
    public void getProductToRedis() {

        QueryProductListRequest request=new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setPageSize(10);
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryProductListResponse queryProductListResponse;
        try {
             queryProductListResponse = client.queryProductList(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if(queryProductListResponse.getBody().success){
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().getList().productInfo;
            redisTemplate.opsForValue().set("product:resource", JSONUtil.toJsonStr(productInfo));
        }

    }

    @Override
    public List<ProductVo> getAllProduct() {
        String s = redisTemplate.opsForValue().get("product:resource");
        List<ProductVo> list = JSONUtil.toList(s, ProductVo.class);
        return list;
    }

    @Override
    public void addDevice(DeviceDto dto) {
        if(deviceMapper.getCountByName(dto.getDeviceName())>0){//有设备
            throw new RuntimeException("已有该设备");
        }
        //设置注册的条件
        RegisterDeviceRequest request=new RegisterDeviceRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        request.setDeviceName(dto.getDeviceName());
        request.setProductKey(dto.getProductKey());
        request.setNickname(dto.getNickname());
        RegisterDeviceResponse registerDeviceResponse;
        //注册
        try {
             registerDeviceResponse = client.registerDevice(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!registerDeviceResponse.getBody().success){
            throw new RuntimeException("注册到iot失败");
        }

        //将Devicedto转成Device

        Device device = BeanUtil.toBean(dto, Device.class);
        //注册成功后 response会返回该设备在iot中的id,并且将此id赋值给device
        String iotId = registerDeviceResponse.getBody().getData().getIotId();
        device.setIotId(iotId);

        if(dto.getLocationType().equals(0)){//是移动版本 不需要粗略的地址
            device.setPhysicalLocationType(-1);
            device.setHaveEntranceGuard(0);
        }
        //获取产品名称
        QueryProductRequest productRequest=new QueryProductRequest();
        productRequest.setProductKey(dto.getProductKey());
        productRequest.setIotInstanceId(aliyunIotProperties.getIotInstanceId());

        QueryProductResponse queryProductResponse;
        try {
            queryProductResponse = client.queryProduct(productRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!queryProductResponse.getBody().success){
            throw new RuntimeException("获取产品名称失败");
        }

        //将查询出来的产品名称付给Device
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        device.setHaveEntranceGuard(0);

        try {
            deviceMapper.insertDevice(device);
        } catch (Exception e) {

           //如果添加失败 删除iot中注册的设备
            DeleteDeviceRequest deviceRequest=new DeleteDeviceRequest();
            deviceRequest.setProductKey(dto.getProductKey());
            deviceRequest.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
            //核心需要知道设备的id
            deviceRequest.setIotId(device.getIotId());

            DeleteDeviceResponse deleteDeviceResponse;
            try {
                deleteDeviceResponse = client.deleteDevice(deviceRequest);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            if(!deleteDeviceResponse.getBody().getSuccess()){
                throw new RuntimeException("删除iot中的device失败");
            }

        }

    }

    @Override
    public PageResponse<DeviceDataVo> pageDevice(Integer pageNum,
                                                 Integer pageSize,
                                                 String deviceName,
                                                 Integer locationType,
                                                 String productKey) {
        PageHelper.startPage(pageNum,pageSize);
        Page<DeviceDataVo> pageDevice=deviceMapper.page(deviceName,locationType,productKey);
        return PageResponse.of(pageDevice,DeviceDataVo.class);
    }

    @Override
    public DeviceVo getDeviceDetailByIotId(DeviceDto deviceDto) {
       DeviceVo deviceVo= deviceMapper.getByIotId(deviceDto.getIotId());
       QueryDeviceDetailRequest request=new QueryDeviceDetailRequest();
       request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
       request.setIotId(deviceVo.getIotId());

        QueryDeviceDetailResponse queryDeviceDetailResponse;

        try {
            queryDeviceDetailResponse = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if(!queryDeviceDetailResponse.getBody().success){
            throw  new RuntimeException("获取iot设备详情数据失败");
        }


        BeanUtil.copyProperties(queryDeviceDetailResponse.getBody().getData(),deviceVo, CopyOptions.create().ignoreNullValue());

        return deviceVo;
    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(DeviceDto deviceDto) {
        //通过数据库的到设备iotId
        DeviceVo device= deviceMapper.getByDeviceName(deviceDto.getDeviceName());
        QueryDevicePropertyStatusRequest request=new QueryDevicePropertyStatusRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        request.setIotId(device.getIotId());
        request.setProductKey(deviceDto.getProductKey());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!queryDevicePropertyStatusResponse.getBody().success){
            throw new RuntimeException("获取传感器数据失败");
        }
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = queryDevicePropertyStatusResponse.getBody().getData();
        return data;
    }

    @Override
    public Map<String, String> getModel(DeviceDto deviceDto) {

        QueryThingModelPublishedRequest request=new QueryThingModelPublishedRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());

        QueryThingModelPublishedResponse queryThingModelPublishedResponse;
        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!queryThingModelPublishedResponse.getBody().success){
            throw new RuntimeException("获取指定产品以发布物模型功能定义详情失败");
        }
        Map<String,String> map=new HashMap<>();
        map.put("thingModelJson",queryThingModelPublishedResponse.getBody().getData().thingModelJson);
        return map;
    }

    //  @NameInMap("DeviceName")
    //        public String deviceName;
    //        @NameInMap("IotId")
    //        public String iotId;
    //        @NameInMap("Nickname")
    //        public String nickname;
    //        @NameInMap("ProductKey")
    //        public String productKey;
    @Override
    public void update(DeviceDto deviceDto) {
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        BatchUpdateDeviceNicknameRequest request=new BatchUpdateDeviceNicknameRequest();


        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> deviceNicknameInfo=new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo iotdevice=new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        //通过mapper获取iotid
        DeviceVo deviceSql = deviceMapper.getByDeviceName(deviceDto.getDeviceName());

        iotdevice.setNickname(deviceDto.getNickname());
        iotdevice.setIotId(deviceSql.getIotId());

        //添加进数组中
        deviceNicknameInfo.add(iotdevice);

        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        request.setDeviceNicknameInfo(deviceNicknameInfo);


        BatchUpdateDeviceNicknameResponse batchUpdateDeviceNicknameResponse;
        try {
            batchUpdateDeviceNicknameResponse = client.batchUpdateDeviceNickname(request);

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
        if(!batchUpdateDeviceNicknameResponse.getBody().success){
            throw new RuntimeException("修改iot的nickname失败");
        }

        deviceMapper.updateDeviceById(device);
    }

    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        DeleteDeviceRequest request=new DeleteDeviceRequest();
        request.setIotId(deviceDto.getIotId());
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        DeleteDeviceResponse deleteDeviceResponse;

        try {
            deleteDeviceResponse = client.deleteDevice(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if(!deleteDeviceResponse.getBody().success){
            throw new RuntimeException("iot删除失败");
        }
        deviceMapper.deleteByIotId(deviceDto.getIotId());


    }
}
